﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using YArchitech.Revit.Electric.Common;

namespace HYRElectric.WirePlace
{
	internal class WireStruct
	{
		public WireStruct(Wire wire)
		{
			this.getWireInfo(wire);
		}

		public Element startElement()
		{
			return this.m_startElement;
		}

		public Element endElement()
		{
			return this.m_endElement;
		}

		public string wireName()
		{
			return this.m_wireName;
		}

		public List<XYZ> wirePoints()
		{
			return this.m_points;
		}

		public List<Wire> wireItems()
		{
			return this.m_wires;
		}

		private void getWireInfo(Wire wire)
		{
			this.getWireList(wire, null, true);
			if (this.m_wires.Count == 1)
			{
				List<Connector> wireConnectors = RevitUtils.GetWireConnectors(this.m_wires[0]);
				this.getConnectElement(wireConnectors[0], this.m_wires[0].Id, null, out this.m_startElement);
				this.getConnectElement(wireConnectors[1], this.m_wires[0].Id, null, out this.m_endElement);
			}
			else
			{
				this.m_startElement = this.getDeviceElement(this.m_wires[0]);
				this.m_endElement = this.getDeviceElement(this.m_wires[this.m_wires.Count - 1]);
			}
			this.getWirePoints();
			for (int i = 0; i < this.m_wires.Count; i++)
			{
				this.m_wireName += this.m_wires[i].Id.ToString();
				if (i != this.m_wires.Count - 1)
				{
					this.m_wireName += "，";
				}
			}
		}

		private void getWirePoints()
		{
			XYZ xyz = null;
			if (this.m_startElement != null)
			{
				xyz = RevitUtils.GetDeviceConnector(this.m_startElement).Origin;
			}
			else if (this.m_endElement != null)
			{
				xyz = RevitUtils.GetDeviceConnector(this.m_endElement).Origin;
				this.m_wires.Reverse();
			}
			foreach (Wire wire in this.m_wires)
			{
				int count = this.m_points.Count;
				List<XYZ> wireVertexs = RevitVersionFuncs.getWireVertexs(wire);
				if (count == 0)
				{
					if (xyz != null && Math.Abs(wireVertexs[0].X - xyz.X) >= this.m_tol && Math.Abs(wireVertexs[0].Y - xyz.Y) >= this.m_tol)
					{
						wireVertexs.Reverse();
					}
				}
				else if (!this.m_points[count - 1].IsAlmostEqualTo(wireVertexs[0]))
				{
					wireVertexs.Reverse();
					wireVertexs.RemoveAt(0);
				}
				else
				{
					wireVertexs.RemoveAt(0);
				}
				this.m_points.InsertRange(count, wireVertexs);
			}
		}

		private Element getDeviceElement(Wire wire)
		{
			List<Connector> wireConnectors = RevitUtils.GetWireConnectors(wire);
			Element result = null;
			int connectElement = this.getConnectElement(wireConnectors[0], wire.Id, null, out result);
			if (2 == connectElement)
			{
				return result;
			}
			connectElement = this.getConnectElement(wireConnectors[1], wire.Id, null, out result);
			if (2 == connectElement)
			{
				return result;
			}
			return null;
		}

		private void getWireList(Wire wire, ElementId idRef, bool isForward = true)
		{
			if (isForward)
			{
				this.m_wires.Insert(0, wire);
			}
			else
			{
				this.m_wires.Add(wire);
			}
			List<Connector> wireConnectors = RevitUtils.GetWireConnectors(wire);
			Element element = null;
			int connectElement = this.getConnectElement(wireConnectors[0], wire.Id, idRef, out element);
			if (1 == connectElement)
			{
				Wire wire2 = element as Wire;
				this.getWireList(wire2, wire.Id, true);
			}
			Element element2 = null;
			connectElement = this.getConnectElement(wireConnectors[1], wire.Id, idRef, out element2);
			if (1 == connectElement)
			{
				Wire wire3 = element2 as Wire;
				this.getWireList(wire3, wire.Id, false);
			}
		}

		private int getConnectElement(Connector connector, ElementId id, ElementId idRef, out Element element)
		{
			element = null;
			ConnectorSet allRefs = connector.AllRefs;
			if (allRefs.Size <= 0)
			{
				return 0;
			}
			foreach (object obj in allRefs)
			{
				Element owner = ((Connector)obj).Owner;
				if (owner.Id != id && owner.Id != idRef)
				{
					element = owner;
				}
			}
			if (element is Wire)
			{
				return 1;
			}
			return 2;
		}

		private List<Wire> m_wires = new List<Wire>();

		private Element m_startElement;

		private Element m_endElement;

		private List<XYZ> m_points = new List<XYZ>();

		private string m_wireName;

		private double m_tol = 1E-05;
	}
}
